﻿using Avalon.Core.Data;
using Avalon.Data;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace Avalon.Repository
{
    public class Repository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
    {
        private AvalonDbContext _context { 
            get { return ContextFactory.Current; } 
            set { ContextFactory.Current = value; } 
        }

        public Repository() { }

        public Repository(AvalonDbContext context)
        {
            _context = context;
        }

        public void Dispose()
        {
            ContextFactory.Reset();
        }

        public IQueryable<TEntity> Get()
        {
            return _context.Set<TEntity>();
        }

        public IQueryable<TEntity> Get(Expression<Func<TEntity, bool>> where)
        {
            return _context.Set<TEntity>().Where(where);
        }

        public TEntity Get(Guid id)
        {
            return _context.Set<TEntity>().FirstOrDefault(e => e.Id == id);
        }

        public void Add(TEntity entity)
        {
            _context.Set<TEntity>().Add(entity);
        }

        public void Update(TEntity entity)
        {
            if (_context.Entry<TEntity>(entity).State == System.Data.EntityState.Detached)
            {
                _context.Entry<TEntity>(entity).State = System.Data.EntityState.Modified;
            }
        }

        public void Delete(Guid id)
        {
            _context.Set<TEntity>().Remove((this as IRepository<TEntity>).Get(id));
        }

        public void Delete(TEntity entity)
        {
            (this as IRepository<TEntity>).Delete(entity.Id);
        }

        public int SaveChanges()
        {
            var result = _context.SaveChanges();
            ContextFactory.Reset();
            return result;
        }


        #region IRepository
        IQueryable IRepository.Get()
        {
            return this.Get();
        }

        object IRepository.Get(Guid id)
        {
            return this.Get(id);
        }

        public void Add(object entity)
        {
            this.Add((TEntity)entity);
        }

        public void Update(object entity)
        {
            this.Update((TEntity)entity);
        }

        public void Delete(object entity)
        {
            this.Delete((TEntity)entity);
        }
        #endregion IRepository
    }
}
